using System;
using System.Collections.Generic;
using System.Linq;

namespace SGEngine.ProfilerEx
{
    public static class MyExtensions
    {
        /// <summary>
        /// 插入排序（最快的排序算法是插入排序。插入排序在列表已经基本有序的情况下表现良好，并且对少量数据进行局部修改时，其时间复杂度为O(n + k)，其中k是修改的次数。）
        /// </summary>
        /// <param name="list"></param>
        /// <param name="comparison"></param>
        /// <typeparam name="T"></typeparam>
        public static void InsertionSort<T>(this List<T> list, Comparison<T> comparison)
        {
            int n = list.Count;
            for (int i = 1; i < n; ++i)
            {
                T key = list[i];
                int j = i - 1;

                while (j >= 0 && comparison(list[j], key) > 0)
                {
                    list[j + 1] = list[j];
                    j = j - 1;
                }
                list[j + 1] = key;
            }
        }
        
        // 归并排序扩展方法
        public static void MergeSort<T>(this List<T> list, Comparison<T> comparison)
        {
            // 辅助函数：合并两个有序数组
            void Merge(List<T> arr, int left, int mid, int right)
            {
                int n1 = mid - left + 1;
                int n2 = right - mid;

                T[] L = new T[n1];
                T[] R = new T[n2];

                // 将数据复制到临时数组 L 和 R
                for (int i = 0; i < n1; i++)
                {
                    L[i] = arr[left + i];
                }
                for (int j = 0; j < n2; j++)
                {
                    R[j] = arr[mid + 1 + j];
                }

                // 合并两个有序数组
                int k = left;
                int p = 0, q = 0;
                while (p < n1 && q < n2)
                {
                    if (comparison(L[p], R[q]) <= 0)
                    {
                        arr[k] = L[p];
                        p++;
                    }
                    else
                    {
                        arr[k] = R[q];
                        q++;
                    }
                    k++;
                }

                // 处理剩余元素
                while (p < n1)
                {
                    arr[k] = L[p];
                    p++;
                    k++;
                }
                while (q < n2)
                {
                    arr[k] = R[q];
                    q++;
                    k++;
                }
            }

            // 归并排序算法
            void Sort(List<T> arr, int left, int right)
            {
                if (left < right)
                {
                    int mid = left + (right - left) / 2;

                    // 递归地对左半部分进行排序
                    Sort(arr, left, mid);
                    // 递归地对右半部分进行排序
                    Sort(arr, mid + 1, right);

                    // 合并已排序的两部分
                    Merge(arr, left, mid, right);
                }
            }

            // 调用归并排序算法
            Sort(list, 0, list.Count - 1);
        }
        
        public static bool TryGetLastValue<T>(this DoubleLinkedList<T> list, out T data) where T : class
        {
            data = null;
            if (list == null || list.Count == 0 || list.Last == null)
            {
                return false;
            }
            data = (T)list.Last.Value;
            return true;
        }
        
        public static bool TryGetLastValue<T>(this LinkedList<T> list, out T data)
        {
            data = default(T);
            if (list == null || list.Count == 0 || list.Last == null)
            {
                return false;
            }
            data = list.Last.Value;
            return true;
        }
        
        public static IOrderedEnumerable<T> Order<T, TKey>(this IEnumerable<T> source, Func<T, TKey> selector, bool ascending)
        {
            if (ascending)
            {
                return source.OrderBy(selector);
            }
            else
            {
                return source.OrderByDescending(selector);
            }
        }

        public static IOrderedEnumerable<T> ThenBy<T, TKey>(this IOrderedEnumerable<T> source, Func<T, TKey> selector, bool ascending)
        {
            if (ascending)
            {
                return source.ThenBy(selector);
            }
            else
            {
                return source.ThenByDescending(selector);
            }
        }
    }
}